"""
xgboost系列丨xgboost建树过程分析及代码实现
https://blog.csdn.net/fengdu78/article/details/112130821
"""

import pandas as pd
import numpy as np

df = pd.read_csv('Container_Crane_Controller_Data_Set.csv', decimal=';').astype(
    {"Power": 'float32', "Speed": 'float32', "Angle": 'float32'})

df['Power'] = (df['Power'].values >= 0.5)
df = df.astype({"Power": 'int32'})

df.rename(columns={"Power": "y", "Speed": 'x1', "Angle": 'x2'}, inplace=True)
print(df)


def log_loss_obj(preds, labels):
    preds = 1.0 / (1.0 + np.exp(-preds))
    grad = preds - labels
    hess = preds * (1.0 - preds)
    return grad, hess


base_predict = np.zeros_like(df.y)
print(base_predict)
g, h = log_loss_obj(base_predict, df.y.values)  # 计算每个样本的g和h
df['g'], df['h'] = g, h

print(df)

print(sorted(df.x1.unique()))


def split_data(df, split_feature, split_value):
    left_instance = df[df[split_feature] < split_value]
    right_instance = df[df[split_feature] >= split_value]
    return left_instance, right_instance


# left_instance, right_instance = split_data(df, 'x1', 2)
# print(left_instance.index.tolist(), right_instance.index.tolist())

reg_lambda = 1
G, H = df.g.sum(), df.h.sum()  # 分裂前全部样本的G/H

res = {}
for thresh_values in sorted(df.x1.unique())[1:]:
    left_instance, right_instance = split_data(df, 'x1', thresh_values)

    G_left, H_left = left_instance[['g', 'h']].sum()  # 分裂后的G_l,H_l

    G_right, H_right = right_instance[['g', 'h']].sum()  # 分裂后的G_r,H_r

    Gain = G_left ** 2 / (H_left + reg_lambda) + G_right ** 2 / \
           (H_right + reg_lambda) - G ** 2 / (H + reg_lambda)  # 分裂后的增益计算

    res.update({thresh_values: [G_left, H_left, G_left, G_right, Gain]})

print(res)

print(pd.DataFrame(res))

